Link to this headingSHA1

  • Merkle–Damgård based hash function
    • Vulnerable to Length extension attack

https://www.synopsys.com/blogs/software-security/forging-sha-1-mac-using-length-extension-attack-python/

Link to this headingCollisions

SHA-1 Collision Strings

%25%50%44%46%2D%31%2E%33%0A%25%E2%E3%CF%D3%0A%0A%0A%31%20%30%20%6F%62%6A%0A%3C%3C%2F%57%69%64%74%68%20%32%20%30%20%52%2F%48%65%69%67%68%74%20%33%20%30%20%52%2F%54%79%70%65%20%34%20%30%20%52%2F%53%75%62%74%79%70%65%20%35%20%30%20%52%2F%46%69%6C%74%65%72%20%36%20%30%20%52%2F%43%6F%6C%6F%72%53%70%61%63%65%20%37%20%30%20%52%2F%4C%65%6E%67%74%68%20%38%20%30%20%52%2F%42%69%74%73%50%65%72%43%6F%6D%70%6F%6E%65%6E%74%20%38%3E%3E%0A%73%74%72%65%61%6D%0A%FF%D8%FF%FE%00%24%53%48%41%2D%31%20%69%73%20%64%65%61%64%21%21%21%21%21%85%2F%EC%09%23%39%75%9C%39%B1%A1%C6%3C%4C%97%E1%FF%FE%01%73%46%DC%91%66%B6%7E%11%8F%02%9A%B6%21%B2%56%0F%F9%CA%67%CC%A8%C7%F8%5B%A8%4C%79%03%0C%2B%3D%E2%18%F8%6D%B3%A9%09%01%D5%DF%45%C1%4F%26%FE%DF%B3%DC%38%E9%6A%C2%2F%E7%BD%72%8F%0E%45%BC%E0%46%D2%3C%57%0F%EB%14%13%98%BB%55%2E%F5%A0%A8%2B%E3%31%FE%A4%80%37%B8%B5%D7%1F%0E%33%2E%DF%93%AC%35%00%EB%4D%DC%0D%EC%C1%A8%64%79%0C%78%2C%76%21%56%60%DD%30%97%91%D0%6B%D0%AF%3F%98%CD%A4%BC%46%29%B1
%25%50%44%46%2D%31%2E%33%0A%25%E2%E3%CF%D3%0A%0A%0A%31%20%30%20%6F%62%6A%0A%3C%3C%2F%57%69%64%74%68%20%32%20%30%20%52%2F%48%65%69%67%68%74%20%33%20%30%20%52%2F%54%79%70%65%20%34%20%30%20%52%2F%53%75%62%74%79%70%65%20%35%20%30%20%52%2F%46%69%6C%74%65%72%20%36%20%30%20%52%2F%43%6F%6C%6F%72%53%70%61%63%65%20%37%20%30%20%52%2F%4C%65%6E%67%74%68%20%38%20%30%20%52%2F%42%69%74%73%50%65%72%43%6F%6D%70%6F%6E%65%6E%74%20%38%3E%3E%0A%73%74%72%65%61%6D%0A%FF%D8%FF%FE%00%24%53%48%41%2D%31%20%69%73%20%64%65%61%64%21%21%21%21%21%85%2F%EC%09%23%39%75%9C%39%B1%A1%C6%3C%4C%97%E1%FF%FE%01%7F%46%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2%56%0B%45%CA%67%D6%88%C7%F8%4B%8C%4C%79%1F%E0%2B%3D%F6%14%F8%6D%B1%69%09%01%C5%6B%45%C1%53%0A%FE%DF%B7%60%38%E9%72%72%2F%E7%AD%72%8F%0E%49%04%E0%46%C2%30%57%0F%E9%D4%13%98%AB%E1%2E%F5%BC%94%2B%E3%35%42%A4%80%2D%98%B5%D7%0F%2A%33%2E%C3%7F%AC%35%14%E7%4D%DC%0F%2C%C1%A8%74%CD%0C%78%30%5A%21%56%64%61%30%97%89%60%6B%D0%BF%3F%98%CD%A8%04%46%29%A1
<details> <summary>URL decode strings.</summary> <pre><code>255044462D312E330A25E2E3CFD30A0A0A312030206F626A0A3C3C2F57696474682032203020522F4865696768742033203020522F547970652034203020522F537562747970652035203020522F46696C7465722036203020522F436F6C6F7253706163652037203020522F4C656E6774682038203020522F42697473506572436F6D706F6E656E7420383E3E0A73747265616D0AFFD8FFFE00245348412D3120697320646561642121212121852FEC092339759C39B1A1C63C4C97E1FFFE017F46DC93A6B67E013B029AAA1DB2560B45CA67D688C7F84B8C4C791FE02B3DF614F86DB1690901C56B45C1530AFEDFB76038E972722FE7AD728F0E4904E046C230570FE9D41398ABE12EF5BC942BE33542A4802D98B5D70F2A332EC37FAC3514E74DDC0F2CC1A874CD0C78305A21566461309789606BD0BF3F98CDA8044629A1</code></pre> <pre><code>255044462D312E330A25E2E3CFD30A0A0A312030206F626A0A3C3C2F57696474682032203020522F4865696768742033203020522F547970652034203020522F537562747970652035203020522F46696C7465722036203020522F436F6C6F7253706163652037203020522F4C656E6774682038203020522F42697473506572436F6D706F6E656E7420383E3E0A73747265616D0AFFD8FFFE00245348412D3120697320646561642121212121852FEC092339759C39B1A1C63C4C97E1FFFE017346DC9166B67E118F029AB621B2560FF9CA67CCA8C7F85BA84C79030C2B3DE218F86DB3A90901D5DF45C14F26FEDFB3DC38E96AC22FE7BD728F0E45BCE046D23C570FEB141398BB552EF5A0A82BE331FEA48037B8B5D71F0E332EDF93AC3500EB4DDC0DECC1A864790C782C76215660DD309791D06BD0AF3F98CDA4BC4629B1</code></pre> </details><br>

Link to this headingPDF Collisions

Take 2 pdfs and generate new versions of both of them to contain a sha1 collision

Install:

#Install Dependencies yay -S ghostscript turbojpeg #Download Github repo git clone https://github.com/nneonneo/sha1collider cd sha1collider #Download sample pdfs wget https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf wget https://unec.edu.az/application/uploads/2014/12/pdf-sample.pdf #Ensure they are diffrent files [gen0@gen0 sha1collider]$ sha256sum dummy.pdf pdf-sample.pdf 3df79d34abbca99308e79cb94461c1893582604d68329a41fd4bec1885e6adb4 dummy.pdf 60bdd13ea4827b8de375c79dc3ff847f83b55bd73b6461523fdf8f843b5a0d5b pdf-sample.pdf [gen0@gen0 sha1collider]$ sha1sum dummy.pdf pdf-sample.pdf 90ffd2359008d82298821d16b21778c5c39aec36 dummy.pdf fc80d59877b4ae21911591b53664b2da1324cf25 pdf-sample.pdf

Generating and testing PDFs:

>>> python3 collide.py dummy.pdf pdf-sample.pdf [14:39:08] INFO: rendering file 1... GPL Ghostscript 9.56.1 (2022-04-04) Copyright (C) 2022 Artifex Software, Inc. All rights reserved. This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY: see the file COPYING for details. Processing pages 1 through 1. Page 1 [...] >>> sha1sum *.pdf 90ffd2359008d82298821d16b21778c5c39aec36 dummy.pdf ed880ae0030504a51ab39eb36b533383d374cd41 out-dummy.pdf ed880ae0030504a51ab39eb36b533383d374cd41 out-pdf-sample.pdf fc80d59877b4ae21911591b53664b2da1324cf25 pdf-sample.pdf >>> sha256sum *.pdf 3df79d34abbca99308e79cb94461c1893582604d68329a41fd4bec1885e6adb4 dummy.pdf 675eb780b254d32bf2cad40d9a9702787048b2fbe33228ec4311f812fa472149 out-dummy.pdf b5b7fdc2b6d9b7f9e7907a6b029cb3246d381b0bc7487b1ec282c5c7557e0fef out-pdf-sample.pdf 60bdd13ea4827b8de375c79dc3ff847f83b55bd73b6461523fdf8f843b5a0d5b pdf-sample.pdf

Link to this headingImplementation

from cryptopals_lib import * class SHA(object): def __init__(self): self.buffers = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0] self.round_constants = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6] def _set_message(self, message): #Convert to bytes if not already byte_message = bytearray(message) #Get Length shifted by 8 and limit to 64bit int input_length_data = asint64(len(byte_message) << 3) #Append 0x80 to the end of the message as a end of message byte byte_message.append(0x80) #Pad the data to a multable of 64 bytes when the 8 byte input_length_data is added while len(byte_message) % 64 != 56: byte_message.append(0x00) #Append the length data to the message byte_message += int_to_bytes_length(input_length_data, 8) return byte_message def _hash_message_chunk(self, chunk): temp_buffers = self.buffers[:] #Create the start of the temp chunks temp_chunks = bytes_to_intarray(chunk, 4, byte_order="big") #Generate the rest of the chunks for index in range(16, 80): temp_chunks.append(shift_rotate_left(temp_chunks[index-3] ^ temp_chunks[index-8] ^ temp_chunks[index-14] ^ temp_chunks[index-16], 1)) #First Rounds itteration for round_itteration in range(20): #print(round_itteration, temp_buffers) #Do Function F (b & c) ^ (~b & d) temp_value = fixedlen_xor((temp_buffers[1] & temp_buffers[2]), (~temp_buffers[1] & temp_buffers[3])) #Add Varables mod 32 #print(shift_rotate_left(temp_buffers[0], 5), temp_value, temp_buffers[4], self.round_constants[0], temp_chunks[round_itteration]) temp_value = asint32(shift_rotate_left(temp_buffers[0], 5) + temp_value + temp_buffers[4] + self.round_constants[0] + temp_chunks[round_itteration]) #Swap values in to the new buffer temp_buffers = [temp_value, temp_buffers[0], shift_rotate_left(temp_buffers[1], 30), temp_buffers[2], temp_buffers[3]] for round_itteration in range(20, 40): #print(round_itteration, temp_buffers) #Do Function G b ^ c ^ d temp_value = fixedlen_xor(temp_buffers[1], fixedlen_xor(temp_buffers[2], temp_buffers[3])) #Add Varables mod 32 temp_value = asint32(shift_rotate_left(temp_buffers[0], 5) + temp_value + temp_buffers[4] + self.round_constants[1] + temp_chunks[round_itteration]) #Swap values in to the new buffer temp_buffers = [temp_value, temp_buffers[0], shift_rotate_left(temp_buffers[1], 30), temp_buffers[2], temp_buffers[3]] for round_itteration in range(40, 60): #print(round_itteration, temp_buffers) #Do Function H (b & c) ^ (b & d) ^ (c & d) temp_value = fixedlen_xor(fixedlen_xor((temp_buffers[1] & temp_buffers[2]), (temp_buffers[1] & temp_buffers[3])), (temp_buffers[2] & temp_buffers[3])) #Add Varables mod 32 temp_value = asint32(shift_rotate_left(temp_buffers[0], 5) + temp_value + temp_buffers[4] + self.round_constants[2] + temp_chunks[round_itteration]) #Swap values in to the new buffer temp_buffers = [temp_value, temp_buffers[0], shift_rotate_left(temp_buffers[1], 30), temp_buffers[2], temp_buffers[3]] for round_itteration in range(60, 80): #print(round_itteration, temp_buffers) #Do Function I b ^ c ^ d temp_value = fixedlen_xor(temp_buffers[1], fixedlen_xor(temp_buffers[2], temp_buffers[3])) #Add Varables mod 32 temp_value = asint32(shift_rotate_left(temp_buffers[0], 5) + temp_value + temp_buffers[4] + self.round_constants[3] + temp_chunks[round_itteration]) #Swap values in to the new buffer temp_buffers = [temp_value, temp_buffers[0], shift_rotate_left(temp_buffers[1], 30), temp_buffers[2], temp_buffers[3]] #Chunks are done with the round #Update the internal buffers with the new data self.buffers = [asint32(self.buffers[0] + temp_buffers[0]), asint32(self.buffers[1] + temp_buffers[1]), asint32(self.buffers[2] + temp_buffers[2]), asint32(self.buffers[3] + temp_buffers[3]), asint32(self.buffers[4] + temp_buffers[4])] def hash(self, message): #Setup message with padding and length data byte_message = self._set_message(message) #Opperate on each of the 64 byte chunks for chunk in to_blocks(byte_message, 64): self._hash_message_chunk(chunk) #Convert Intagers to Byte string output = b"" for x in self.buffers: output += (x).to_bytes(4, byteorder='big') return output def hash_digest(self, message): return self.hash(message).hex() if __name__ == '__main__': testsha = SHA() print(testsha.hash_digest(b"")) #da39a3ee5e6b4b0d3255bfef95601890afd80709 testsha = SHA() print(testsha.hash_digest(b"a")) #86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 testsha = SHA() print(testsha.hash_digest(b"c7840924e344f6d3934999be91f1f079c759cfc1d7ebb38655b49415df9a1c67b9345d01c0c0aaacd51357f74e356d75fc7e22322637d54d43331b143e268b297eee06be41abefdd2b78cdc33a7f9372e9f4df44d0c5d3a981c7084b2cc6be181b13251f2151cc03d2b0c6d001c13105dd1d5bd7e3200696545ed7ed9c1dc2662fe34f35b8caffbb0466b129736fa4b0ad18e21297836814561cdeaba49b345b6f5e3717a322485acb01ba9af6fe085052bdd158ab930b80b0c96eb2fd28570e9c81579f304443a8c3e4c4e3c0968444acc65e000730b4399719936c7e141d40b6d721f4fa97254465a9ddf51f1e70ad340ad8cc27671fd8a28bda7ec2ce475ebf1819b448f8804c2a2df277ae613974c889a7dc0bfa42698e29e663e0d5591324221267fc5d3ff101e81afdb4f9fb4a40c025bbab9c5809bd297904e6ca3b8036cc4ead33ea28639803cac1a5a67572bbc7947254d15d8befd44e7125920ba5f6f6e87cf07e75e56ea47f3817ff35de2033652a5c9a797d44b811c6482a345d0201a3064b6dd9e6b86735c16efd34120a3adb3496fc52472175056bef762f76e93bd6e7253f4c2baaddeb7d2aa1ee187909fc842276021ce38c82ad57594eb416f80fa0804437a501b21e9f8643d6120b9c0ab5d7624e1c3354c473446757dd1c722f5703055598d16d2458b77defbab48b87ca205339e4417a4486958d96db")) #0a1a0fbb3c5bfd22f5fdfdd17c9bf2c9b1281fa4